/**
 * @file
 */
#ifndef WII_GI_C_ENGINE_H
#define WII_GI_C_ENGINE_H
#include <stdlib.h>
#include <stdio.h>
#include <gctypes.h>
#include "pngu.h"
#define HAVE_BOOLEAN
#include "jpeglib.h"
#include <wiiuse/wpad.h>
#include <queue>

#include "c_Singleton.h"
#include "c_AppState.h"
#include "c_Flags.h"
#include "c_Rect.h"
#include "c_Vector2d.h"
#include "e_Status.h"
#include <vector>

namespace wiigi
{
   class c_Texture;
   class c_Sprite;
   
   /**
    * This class defines a top level game engine.
    */
   class c_Engine : public c_Singleton< c_Engine >, public c_Flags< u32 >
   {
      
      public:
         
         static const u32 d_NumberOfSprites = 256;
         
         
         //Defines some flags
         static const u32 d_HomePressed   = 0x00000001;  /**< Home button has been pressed */
         static const u32 d_CreateConsole = 0x00000002;  /**< if set when engine is starting up then a FB for the console will be built */
         static const u32 d_ShowConsole   = 0x00000004;  /**< If true, then console will be shown in place of graphics */
         static const u32 d_InitNetwork   = 0x00000008;  /**< true if network sub system should be initialised */
      public:
         
         int startEngine(int argc, char **argv);
      
         void addState( c_AppState* State );
         
         /**
          * set which state will be next
          *
          * @param Name Name of next state
          */
         void setNextState( const std::string& Name )
         {
            m_NextStateName = Name;
         }
         
      private:
         friend class c_Singleton< c_Engine >;
         c_Engine( void );
         ~c_Engine();
         
      //
      // c_Engine.cpp
      //-------------------
      private:
         void runApp( void );
      
      //
      // c_Engine_Input.cpp
      //-------------------
      private:
         void initInput( void );
         void scanInputDevices( void );
         
      //
      // c_Engine_Network.cpp
      //---------------------
      private:
         void initNetwork( void );
         
      //
      // c_Engine_Sprite.cpp
      //-------------------
      public:
         c_Sprite* createSprite( 
            c_Texture* TextureHandle
         );
                                    
         c_Sprite* createSprite( 
            c_Texture* TextureHandle,
            c_u32Rect& FrameSize
         );
         
         c_Sprite* createSprite( 
            c_Texture* TextureHandle,
            c_u32Rect& FrameSize,
            u32              FrameCnt
         );
      private:
         e_Status initSprites( void );   
      //
      // c_Engine_Texture.cpp
      //-------------------
      public:   
         c_Texture* createTexture( const unsigned char Buffer[] );
         c_Texture* loadTexture( const char* FileName );
         
      //
      // c_Engine_Video.cpp
      //-------------------
      public:
          void setBackgroundColour( GXColor& Colour );
      private:
         e_Status initVideo( void );
         void closeVideo( void );
         void updateDisplay( void );
        
         
      private:
         //State related members
         std::map<std::string, c_AppState*> m_States;
         std::string m_CurrentStateName;
         std::string m_NextStateName;
            
      private:
         //graphics/video related members
         GXRModeObj  m_GX_RmodeObj;
         
         static const u32 d_NumberFrameBuffers = 2;
         u32          m_CurrentFrameBuffer; 
         void*        m_FrameBuffer[ d_NumberFrameBuffers ];
         static const u32 d_GP_FIFO_Size = 256 * 1024;
         u8*          m_GP_FIFO;
         static const u32 d_DrawQ_Size = 256;
         std::queue< c_Sprite* > m_DrawQ;
         
         c_f32Rect   m_VisibleArea;
         
         void*       m_ConsoleFB;

      private:
         //Sprites
         std::vector< c_Sprite* > m_FreeSprites;
   
         
         
       public:  
         static Mtx         m_GXmodelView2D;
   };    
   
}

#endif
